package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 发布动态
     *  1、将图片上传到阿里云，获取地址
     *  2、构造动态对象
     *  3、调用API保存动态
     */
    public void movements(String textContent, MultipartFile[] imageContent) throws IOException {
        //1、将图片上传到阿里云，获取地址
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String url = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(url);
        }
        //2、构造动态对象
        Movement movement = new Movement();
        movement.setUserId(UserHolder.getUserId());
        movement.setCreated(System.currentTimeMillis());
        movement.setMedias(medias);
        movement.setTextContent(textContent);
        //3、调用API保存动态
        String monvementId = movementApi.save(movement);
        //4、发送消息：消息是动态的id
        mqMessageService.sendAudiService(monvementId);
    }

    /**
     * 查询我的动态
     */
    public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {
        //1、调用API查询当前用户发布的动态列表  List<Movement>
        List<Movement> movements = movementApi.findByUserId(page,pagesize,userId);
        //2、判断动态列表是否为空，如果未空，返回空
        if(movements == null || movements.size()<=0) {
            return new PageResult();
        }
        //3、查询用户详情 -- 根据用户id查询动态
        UserInfo userInfo = userInfoApi.findById(userId);
        //4、如果不为空，一个Movement对象转化一个vo对象   10个动态
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : movements) {
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //判断：从redis查询是否存在数据
            String key = Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY+UserHolder.getUserId();
            Boolean hashLike = redisTemplate.opsForHash().hasKey(key, hashKey);
            if(hashLike) {
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        //5、构造返回
        return new PageResult(page,pagesize,0l,vos);
    }

    /**
     * 查询好友动态
     *    根据friendId查询时间线数据，查询动态
     */
    public PageResult findByFriendId(Integer page, Integer pagesize) {
        //1、获取当前用户id，可见人id
        Long friendId = UserHolder.getUserId();
        //2、调用api查询数据  List<Movement>
        List<Movement> movements = movementApi.findByFriendId(page,pagesize,friendId);

        return initPage(movements,page,pagesize);
    }
    //公共的方法
    public PageResult initPage(List<Movement> movements,Integer page, Integer pagesize) {
        //3、判断动态列表是否为空，如果未空，返回空
        if(movements == null || movements.size()<=0) {
            return new PageResult();
        }

        List<Long> ids = CollUtil.getFieldValues(movements, "userId", Long.class);
        //map集合，存放了用户id和详情的对应关系
        Map<Long,UserInfo> map = userInfoApi.findByIds(ids);

        //4、一个Movement转化一个MovementVo
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : movements) {
            //查询当前动态发布人的详情
            UserInfo userInfo = map.get(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            //判断：从redis查询是否存在数据
            String key = Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY+UserHolder.getUserId();
            Boolean hashLike = redisTemplate.opsForHash().hasKey(key, hashKey);
            if(hashLike) {
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        //5、构造返回值
        return new PageResult(page,pagesize,0l,vos);
    }

    //查询推荐动态
    public PageResult findByRecommend(Integer page, Integer pagesize) {
        //1、拼接Reids中的key
        String key = "MOVEMENTS_RECOMMEND_"+UserHolder.getUserId();
        //2、从redis中查询数据
        String value = redisTemplate.opsForValue().get(key);
        //3、如果redis中数据不存在，从MongoDb中随机查询一些数据展示
        List<Movement> movements = new ArrayList<>();
        if(StringUtils.isEmpty(value)) {
            movements = movementApi.randomMovements(pagesize);
        }else {
            //4、如果redis中数据存在
            String ids [] = value.split(",");
            //调用API，在api层通过MongoTemplate分页查询，返回数据列表
            movements = movementApi.findByIds(page,pagesize,ids);
        }
        //构造返回值
        return initPage(movements,page,pagesize);
    }

    //根据id查询
    public MovementsVo findById(String id) {
        //1、调用API查询动态，Movement对象
        Movement movement = movementApi.findById(id);
        //2、构造MovementsVo  （Userinfo ，Movement对象）
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        return MovementsVo.init(userInfo,movement);
    }


    @DubboReference
    private VisitorsApi visitorsApi;

    /**
     *  查看首页的最新访客
     *      根据userId和date查询
     */
    public List<TodayBest> visitors() {
        //1、获取用户id
        Long userId = UserHolder.getUserId();
        //2、获取上文查看访客详情的时间
        String key = Constants.VISITORS_USER+userId;
        String value = redisTemplate.opsForValue().get(key);
        Long time = 0l;
        if(!StringUtils.isEmpty(value)) {
            time = Long.valueOf(value);
        }
        //3、调用API根据用户id和访问时间查询数据，要查询5条 List<Visitors>
        List<Visitors> list = visitorsApi.findByUserId(userId,time);
        if(list == null || list.size()<=0) {
            return new ArrayList<>();
        }
        //4、转化VO
        List<Long> ids = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids);
        List<TodayBest> vos = new ArrayList<>();
        //一个visitors构造一个TodayBest；
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            TodayBest vo = TodayBest.init(userInfo, visitors);
            vos.add(vo);
        }
        return vos;
    }
}
